home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
source
/
demostuf
/
light1.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1994-07-25
|
10KB
|
574 lines
program lightsource1;
{
Lightsourced (blenk, really) vector #1
- by Bjarke Viksφe
feb 1994
THIS PROGRAM WAS CODED BY BJARKE VIKS0E.
YOU ARE FREE TO DO WHATEVER YOU WANT WITH THIS PIECE OF CODE.
E-MAIL ME AT: dat92230@rix02.lyngbyes.dk IN 1994 FOR CHAT AND CODE.
Pretty basic. Rotate coords and draw polygons on screen. I use
a different polygon-drawing scheme that all other coders on PC I think.
Starting x-pos and ending x-pos are calculated for each horizontal
line of the whole polygon before it's drawn on the screen.
So we could technically do n-sided polygons just as easy.
Takes too long time because of erasing of screen before drawing.
Need to come up with some idea to skip that...
}
{$DEFINE DEBUG}
uses
DEMOINIT;
const
ANTAL_FACES = 6;
ANTAL_COORDS = 8;
box = 140; {size of box}
type
facetype = RECORD
l1,l2,l3,l4 : byte;
end;
var
slope : array[0..399] of integer;
face : array[1..ANTAL_FACES] of facetype;
light : array[1..ANTAL_FACES] of byte;
cbuffer : array[0..ANTAL_COORDS*2-1] of integer;
miny,maxy : integer;
scrminy,scrmaxy : integer;
lastscrminy, lastscrmaxy : integer;
sinustabel : array[0..639] of integer;
v1,v2,v3 : word;
cos1,sin1,cos2,sin2,cos3,sin3 : integer;
xkoord,ykoord,zkoord,
n : integer;
const
display1 : integer = $0000;
display2 : integer = $4000;
coords : array[0..ANTAL_COORDS*3-1] of integer =
(box,box,-box, -box,box,-box, -box,-box,-box, box,-box,-box,
box,box,box, -box,box,box, -box,-box,box, box,-box,box);
(*------------------------------------------------*)
procedure SetupSinus;
var
i : integer;
v, vadd : real;
begin
v:=0.0;
vadd:=(2.0*pi/512.0);
for i:=0 to 639 do begin
sinustabel[i]:=round(sin(v)*32767);
v:=v+vadd;
end;
end;
procedure SetupCoords;
begin
with face[1] do begin l1:=3; l2:=2; l3:=1; l4:=0; end;
with face[2] do begin l1:=4; l2:=5; l3:=6; l4:=7; end;
with face[3] do begin l1:=0; l2:=1; l3:=5; l4:=4; end;
with face[4] do begin l1:=1; l2:=2; l3:=6; l4:=5; end;
with face[5] do begin l1:=2; l2:=3; l3:=7; l4:=6; end;
with face[6] do begin l1:=3; l2:=0; l3:=4; l4:=7; end;
end;
procedure InitDemo;
var
i : integer;
begin
Screen_Off;
ClearWholeScreen;
SetupSinus;
SetupCoords;
scrminy := 0; scrmaxy := 200;
lastscrminy := 0; lastscrmaxy := 200;
v1:=0; v2:=0; v3:=0;
Screen_On;
end;
(*------------------------------------------------*)
procedure SwapDisplay;
var
temp : word;
begin
temp:=display2;
display2:=display1;
display1:=temp;
SetAddress(Ptr(SEGA000,display2));
end;
procedure ClearScreen(y1,y2 : integer); assembler;
asm
mov dx,$3C4
mov ax,$0F02
out dx,ax
mov bx,y1 {clear box around vector - only y-coords are actually}
mov dx,y2 {used for calculation... x-coords are constant}
sub dx,bx
cmp dx,200
ja @done
lea si,ytabel
add bx,bx
mov di,[si+bx]
add di,display1
add di,16
mov es,SEGA000
DB LONG; xor ax,ax
mov bx,48/4
@loop:
mov cx,bx
rep; DB LONG; stosw
add di,WIDTH-48
dec dl
jnz @loop
@done:
end;
(*------------------------------------------------*)
procedure ClearSlope; assembler;
asm
mov ax,ds
mov es,ax
lea di,slope
DB LONG; mov ax,$8000; DW $8000;
cld
mov cx,200
rep; DB LONG; stosw
end;
procedure CalcSlope(l1,l2 : integer); assembler;
var
ysize : integer;
asm
lea si,cbuffer
mov bx,l1
shl bx,2
mov cx,[si+bx]
mov dx,[si+bx+2]
mov bx,l2
shl bx,2
add si,bx
mov ax,[si]
mov bx,[si+2]
cmp bx,dx
jle @noswap
xchg ax,cx
xchg bx,dx
@noswap:
cmp bx,miny
jae @miny
mov miny,bx
@miny:
cmp dx,maxy
jbe @maxy
mov maxy,dx
@maxy:
sub dx,bx
mov ysize,dx
add bx,bx
add bx,bx
lea si,slope
add si,bx
push ax
sub cx,ax
inc cx
and dx,dx
jz @zero
cmp dl,1
jne @not1
dec cx
mov dx,cx
xor ax,ax
jmp NEAR PTR @one
@not1:
cmp dl,2
jne @not2
mov ax,$7FFF
imul cx
jmp NEAR PTR @one
@not2:
mov dx,$0001
mov ax,$0000
idiv ysize
imul cx
@one:
pop cx
xor bx,bx
mov di,$8000
@loop:
cmp [si],di
jne @other
mov [si],cx
add si,4
add bx,ax
adc cx,dx
dec ysize
jnz @loop
jmp NEAR PTR @zero
@other:
mov [si+2],cx
add si,4
add bx,ax
adc cx,dx
dec ysize
jnz @loop
@zero:
end;
(*------------------------------------------------*)
procedure CalcVinkel;
begin
sin1:=sinustabel[v1]; cos1:=sinustabel[v1+128];
sin2:=sinustabel[v2]; cos2:=sinustabel[v2+128];
sin3:=sinustabel[v3]; cos3:=sinustabel[v3+128];
v1:=(v1+2) AND 511;
v2:=(v2-1) AND 511;
v3:=(v3+1) AND 511;
end;
procedure RotateAllCoords; assembler;
{really fast assembly rotating around all three axis + perspective
calculations. Takes an coord. array, coords, and puts rotated coords
in cbuffer (only x,y are stored...)}
asm
mov ax,ds
mov es,ax
lea si,coords
lea di,cbuffer
mov n,ANTAL_COORDS
cld
@loop:
lodsw
mov xkoord,ax
lodsw
mov ykoord,ax
lodsw
mov zkoord,ax
mov ax,xkoord {rotate around Z-axis}
push ax
imul Cos1
add ax,ax
adc dx,dx
mov bx,dx
mov ax,ykoord
imul Sin1
add ax,ax
adc dx,dx
sub bx,dx
mov xkoord,bx
pop ax
imul Sin1
add ax,ax
adc dx,dx
mov bx,dx
mov ax,ykoord
imul Cos1
add ax,ax
adc dx,dx
add bx,dx
mov ykoord,bx
mov ax,ykoord {rotate around Y-axis}
push ax
imul Cos2
add ax,ax
adc dx,dx
mov bx,dx
mov ax,zkoord
imul Sin2
add ax,ax
adc dx,dx
sub bx,dx
mov ykoord,bx
pop ax
imul Sin2
add ax,ax
adc dx,dx
mov bx,dx
mov ax,zkoord
imul Cos2
add ax,ax
adc dx,dx
add bx,dx
mov zkoord,bx
mov ax,xkoord {rotate around X-axis}
push ax
imul Cos3
add ax,ax
adc dx,dx
mov bx,dx
mov ax,zkoord
imul Sin3
add ax,ax
adc dx,dx
sub bx,dx
mov xkoord,bx
pop ax
imul Sin3
add ax,ax
adc dx,dx
mov bx,dx
mov ax,zkoord
imul Cos3
add ax,ax
adc dx,dx
add bx,dx
mov zkoord,bx
add bx,800
and bx,bx
jnz @zero
mov bl,1
@zero:
mov ax,xkoord
cwd
mov dl,ah
mov ah,al
xor al,al
idiv bx
add ax,160
stosw
mov ax,ykoord
cwd
mov dl,ah
mov ah,al
xor al,al
idiv bx
add ax,100
stosw
dec n
jne @loop
end;
function FaceShown(i : integer; l1,l2,l3 : byte) : boolean;
var
a,b : longint;
begin
a := longmul(cbuffer[l1]-cbuffer[l2],cbuffer[l3+1]-cbuffer[l2+1]);
b := longmul(cbuffer[l1+1]-cbuffer[l2+1],cbuffer[l3]-cbuffer[l2]);
light[i] := longdiv(a-b,200);
FaceShown := (a-b) > 0;
end;
procedure FillShape(y,ysize : integer; color : byte); assembler;
const
pixelarray1 : array[0..3] of byte = (0,14,12,8);
pixelarray2 : array[0..3] of byte = (0,1,3,7);
asm
cmp ysize,200
jae @done
mov ax,y
add ax,ax
mov si,ax
mov di,[si+OFFSET ytabel]
add di,display1
lea si,slope
add ax,ax
add si,ax
mov es,SEGA000
mov bl,color { color in BL }
{doing this outside is a bit risky}
mov dx,$3C4
mov al,$02
out dx,al
{set dir.flag}
cld
@yloop:
lodsw
mov dx,ax
lodsw
cmp ax,dx
jle @exchange
xchg ax,dx
@exchange:
cmp dx,0
jl @filledout_fast
cmp ax,320
jge @filledout_fast
cmp ax,0
jge @cut1
xor ax,ax
@cut1:
cmp dx,319
jle @cut2
mov dx,319
@cut2:
push si
push di
mov cx,dx
sub dx,ax
mov si,dx { size in si at this moment... }
mov dx,ax { get x pos }
shr ax,2
add di,ax
shr cx,2
cmp ax,cx { size is <= 4 if on same }
jne @notsamebyte { byteoffset... special case }
mov cx,si
and cx,cx
jz @filledout
mov al,00001111b
dec cl
xor cl,3
shr al,cl
mov cl,dl
and cl,3
shl al,cl
mov dx,$3C5
out dx,al
mov al,bl
stosb
jmp NEAR PTR @filledout
@notsamebyte:
mov cx,si
and dx,3 {start painting a line}
jz @OnRightByte
mov si,dx
mov al,BYTE PTR pixelarray1+si
dec dl
xor dl,$03
sub cx,dx
mov dx,$3C5
out dx,al
mov al,bl
stosb
@OnRightByte:
mov dx,$3C5
mov al,$F
out dx,al
mov al,bl
mov dx,cx
test di,1 {make sure we fill word on even boundary}
jz @oneven {this check is actually worth it!}
cmp dx,4
jl @only4left
stosb
sub dx,4
@oneven:
mov cx,dx {fill as many words we can}
and dx,7
shr cx,3
jz @only8left
mov ah,al
rep stosw
@only8left:
test dl,4 {also fill a possible whole last-byte}
jz @only4left
stosb
sub dl,4
@only4left:
and dl,dl {and also the last few pixels}
jz @filledout
mov si,dx
mov dx,$3C5
mov al,BYTE PTR pixelarray2+si
out dx,al
mov al,bl
stosb
@filledout:
pop di
pop si
@filledout_fast:
add di,WIDTH
dec ysize
jnz @yloop
@done:
end;
procedure RunOnce;
var
i : integer;
begin
SwapDisplay;
VBLANK;
{$IFDEF DEBUG}
SetRGB(0,30,0,0);
{$ENDIF}
for i:=1 to ANTAL_FACES do setRGB(i,light[i],light[i],light[i]);
ClearScreen(lastscrminy,lastscrmaxy);
lastscrminy := scrminy; lastscrmaxy := scrmaxy;
scrminy := 200; scrmaxy := 0;
CalcVinkel;
RotateAllCoords;
for i:=1 to ANTAL_FACES do begin
with face[i] do if FaceShown(i, l1 shl 1,l2 shl 1,l3 shl 1) then begin
ClearSlope;
miny := 200; maxy := 0;
CalcSlope(l1,l2);
CalcSlope(l2,l3);
CalcSlope(l3,l4);
CalcSlope(l4,l1);
FillShape(miny, maxy-miny, i);
if (miny < scrminy) then scrminy := miny;
if (maxy > scrmaxy) then scrmaxy := maxy;
end;
end;
{$IFDEF DEBUG}
SetRGB(0,0,0,0);
{$ENDIF}
end;
begin
OpenScreen;
InitDemo;
SetAllInterrupts;
repeat RunOnce until Key='e';
RestoreAllInterrupts;
CloseScreen;
end.